#include "BackgroundRenderer.h"
#include <iostream>

BackgroundRenderer::BackgroundRenderer()
    : m_assetManager(AssetManager::GetInstance())
    , m_renderMode(RenderMode::Stretch)
    , m_position(0, 0)
    , m_parallaxFactor(1.0f, 1.0f)
    , m_alpha(1.0f)
    , m_worldWidth(2000.0f)
    , m_worldHeight(800.0f)
{
}

BackgroundRenderer::~BackgroundRenderer()
{
}

bool BackgroundRenderer::SetBackground(const std::string& textureId, const std::wstring& texturePath)
{
    // 先创建或获取纹理资源
    auto textureAsset = m_assetManager->CreateAsset<TextureAsset>(textureId, texturePath);
    if (!textureAsset)
    {
        std::cout << "Failed to create texture asset: " << textureId << std::endl;
        return false;
    }

    // 加载纹理资源
    if (!textureAsset->Load())
    {
        std::cout << "Failed to load texture: " << textureId << std::endl;
        return false;
    }

    m_textureAsset = textureAsset;
    m_currentTextureId = textureId;

    std::cout << "Background texture loaded successfully: " << textureId << std::endl;
    return true;
}

bool BackgroundRenderer::SetBackground(const std::string& textureId)
{
    auto textureAsset = m_assetManager->GetAsset<TextureAsset>(textureId);
    if (!textureAsset)
    {
        std::cout << "Texture asset not found: " << textureId << std::endl;
        return false;
    }

    if (!textureAsset->IsLoaded())
    {
        if (!textureAsset->Load())
        {
            std::cout << "Failed to load texture: " << textureId << std::endl;
            return false;
        }
    }

    m_textureAsset = textureAsset;
    m_currentTextureId = textureId;
    return true;
}

void BackgroundRenderer::Render(const Vector2& cameraOffset)
{
    if (!HasValidTexture())
        return;

    Vector2 offset = Vector2(
        cameraOffset.x * m_parallaxFactor.x,
        cameraOffset.y * m_parallaxFactor.y
    );    switch (m_renderMode)
    {
    case RenderMode::Stretch:
        RenderStretched(offset);
        break;
    case RenderMode::Tile:
        RenderTiled(offset);
        break;
    case RenderMode::Center:
        RenderCentered(offset);
        break;
    case RenderMode::FitWidth:
        RenderFitWidth(offset);
        break;
    case RenderMode::FitHeight:
        RenderFitHeight(offset);
        break;
    case RenderMode::WorldTile:
        RenderWorldTiled(offset);
        break;
    case RenderMode::FitWorld:
        RenderFitWorld(offset);
        break;
    case RenderMode::FitWorldKeepRatio:
        RenderFitWorldKeepRatio(offset);
        break;
    }
}

void BackgroundRenderer::SetParallaxFactor(float factorX, float factorY)
{
    m_parallaxFactor.x = factorX;
    m_parallaxFactor.y = factorY;
}

void BackgroundRenderer::SetAlpha(float alpha)
{
    m_alpha = (std::max)(0.0f, (std::min)(1.0f, alpha));
}

void BackgroundRenderer::SetWorldBounds(float width, float height)
{
    m_worldWidth = width;
    m_worldHeight = height;
}

int BackgroundRenderer::GetWidth() const
{
    return m_textureAsset ? m_textureAsset->GetWidth() : 0;
}

int BackgroundRenderer::GetHeight() const
{
    return m_textureAsset ? m_textureAsset->GetHeight() : 0;
}

bool BackgroundRenderer::HasValidTexture() const
{
    return m_textureAsset && m_textureAsset->IsLoaded() && m_textureAsset->GetImage();
}

void BackgroundRenderer::RenderStretched(const Vector2& offset)
{
    IMAGE* image = m_textureAsset->GetImage();
    if (!image) return;

    // 获取屏幕尺寸
    int screenWidth = getwidth();
    int screenHeight = getheight();

    // 计算背景位置，考虑视差效果
    int bgX = static_cast<int>(m_position.x - offset.x);
    int bgY = static_cast<int>(m_position.y - offset.y);

    // 使用putimage进行拉伸渲染，拉伸到整个屏幕
    putimage(bgX, bgY, screenWidth, screenHeight, image, 0, 0);
}

void BackgroundRenderer::RenderTiled(const Vector2& offset)
{
    IMAGE* image = m_textureAsset->GetImage();
    if (!image) return;

    int screenWidth = getwidth();
    int screenHeight = getheight();
    int texWidth = image->getwidth();
    int texHeight = image->getheight();

    // 计算视差偏移后的有效偏移
    float effectiveOffsetX = offset.x * m_parallaxFactor.x;
    float effectiveOffsetY = offset.y * m_parallaxFactor.y;

    // 计算起始位置，考虑偏移和视差
    int startX = static_cast<int>(m_position.x - effectiveOffsetX) % texWidth;
    int startY = static_cast<int>(m_position.y - effectiveOffsetY) % texHeight;

    if (startX > 0) startX -= texWidth;
    if (startY > 0) startY -= texHeight;

    // 平铺渲染，确保覆盖整个屏幕
    for (int y = startY; y < screenHeight; y += texHeight)
    {
        for (int x = startX; x < screenWidth; x += texWidth)
        {
            RenderImage(image, x, y, m_alpha);
        }
    }
}

void BackgroundRenderer::RenderCentered(const Vector2& offset)
{
    IMAGE* image = m_textureAsset->GetImage();
    if (!image) return;

    int screenWidth = getwidth();
    int screenHeight = getheight();
    int texWidth = image->getwidth();
    int texHeight = image->getheight();

    int centerX = (screenWidth - texWidth) / 2;
    int centerY = (screenHeight - texHeight) / 2;

    RenderImage(image,
        static_cast<int>(centerX + m_position.x - offset.x),
        static_cast<int>(centerY + m_position.y - offset.y),
        m_alpha);
}

void BackgroundRenderer::RenderFitWidth(const Vector2& offset)
{
    IMAGE* image = m_textureAsset->GetImage();
    if (!image) return;

    int screenWidth = getwidth();
    int screenHeight = getheight();
    int texWidth = image->getwidth();
    int texHeight = image->getheight();

    float scale = static_cast<float>(screenWidth) / texWidth;
    int scaledHeight = static_cast<int>(texHeight * scale);
    int centerY = (screenHeight - scaledHeight) / 2;

    putimage(static_cast<int>(m_position.x - offset.x),
        static_cast<int>(centerY + m_position.y - offset.y),
        screenWidth, scaledHeight, image, 0, 0);
}

void BackgroundRenderer::RenderFitHeight(const Vector2& offset)
{
    IMAGE* image = m_textureAsset->GetImage();
    if (!image) return;

    int screenWidth = getwidth();
    int screenHeight = getheight();
    int texWidth = image->getwidth();
    int texHeight = image->getheight();

    float scale = static_cast<float>(screenHeight) / texHeight;
    int scaledWidth = static_cast<int>(texWidth * scale);
    int centerX = (screenWidth - scaledWidth) / 2;

    putimage(static_cast<int>(centerX + m_position.x - offset.x),
        static_cast<int>(m_position.y - offset.y),
        scaledWidth, screenHeight, image, 0, 0);
}

void BackgroundRenderer::RenderImage(IMAGE* image, int x, int y, float alpha)
{
    if (!image) return;

    if (alpha >= 1.0f)
    {
        putimage(x, y, image);
    }
    else
    {
        // 如果需要透明度渲染，这里可以实现更复杂的Alpha混合
        // 暂时使用普通渲染
        putimage(x, y, image);
    }
}

void BackgroundRenderer::RenderWorldTiled(const Vector2& offset)
{
    IMAGE* image = m_textureAsset->GetImage();
    if (!image) return;

    int screenWidth = getwidth();
    int screenHeight = getheight();
    int texWidth = image->getwidth();
    int texHeight = image->getheight();

    // 计算视差偏移后的有效偏移
    float effectiveOffsetX = offset.x * m_parallaxFactor.x;
    float effectiveOffsetY = offset.y * m_parallaxFactor.y;

    // 计算起始位置，确保背景能无缝滚动
    // 使用模运算确保背景图片的连续性
    int startX = static_cast<int>(-effectiveOffsetX) % texWidth;
    int startY = static_cast<int>(-effectiveOffsetY) % texHeight;

    // 如果起始位置为正，向前移动一个纹理单位以确保覆盖
    if (startX > 0) startX -= texWidth;
    if (startY > 0) startY -= texHeight;

    // 扩展渲染范围，确保在摄像机移动时不会露出空白
    int extendedStartX = startX - texWidth;
    int extendedStartY = startY - texHeight;
    int extendedEndX = screenWidth + texWidth;
    int extendedEndY = screenHeight + texHeight;

    // 平铺渲染背景
    for (int y = extendedStartY; y < extendedEndY; y += texHeight)
    {
        for (int x = extendedStartX; x < extendedEndX; x += texWidth)
        {
            RenderImage(image, x, y, m_alpha);
        }
    }
}

void BackgroundRenderer::RenderFitWorld(const Vector2& offset)
{
    IMAGE* image = m_textureAsset->GetImage();
    if (!image) return;

    int screenWidth = getwidth();
    int screenHeight = getheight();

    // 计算背景在世界坐标系中的位置
    // 考虑视差效果和摄像机偏移
    float bgWorldX = m_position.x - (offset.x * m_parallaxFactor.x);
    float bgWorldY = m_position.y - (offset.y * m_parallaxFactor.y);

    // 将背景图片拉伸到整个世界大小，然后根据摄像机位置显示相应部分
    int texWidth = image->getwidth();
    int texHeight = image->getheight();

    // 计算在屏幕上显示的源矩形区域（基于摄像机在世界中的位置）
    float cameraXInWorld = offset.x;
    float cameraYInWorld = offset.y;

    // 计算源图像中对应的区域（按比例映射）
    int srcX = static_cast<int>((cameraXInWorld / m_worldWidth) * texWidth);
    int srcY = static_cast<int>((cameraYInWorld / m_worldHeight) * texHeight);
    int srcWidth = static_cast<int>((screenWidth / m_worldWidth) * texWidth);
    int srcHeight = static_cast<int>((screenHeight / m_worldHeight) * texHeight);

    // 确保源区域不超出图像边界
    srcX = (std::max)(0, (std::min)(srcX, texWidth - 1));
    srcY = (std::max)(0, (std::min)(srcY, texHeight - 1));    srcWidth = (std::min)(srcWidth, texWidth - srcX);
    srcHeight = (std::min)(srcHeight, texHeight - srcY);

    // 渲染到整个屏幕
    if (srcWidth > 0 && srcHeight > 0) {
        // 使用 putimage 的正确重载：putimage(dstX, dstY, dstW, dstH, srcImg, srcX, srcY, SRCCOPY)
        // 然后使用 StretchBlt 或分步骤处理
        putimage(0, 0, screenWidth, screenHeight, image, srcX, srcY, SRCCOPY);
    }
}

void BackgroundRenderer::RenderFitWorldKeepRatio(const Vector2& offset)
{
    IMAGE* image = m_textureAsset->GetImage();
    if (!image) return;

    int screenWidth = getwidth();
    int screenHeight = getheight();
    int texWidth = image->getwidth();
    int texHeight = image->getheight();

    // 计算缩放比例，保持图片比例不变
    float worldRatio = m_worldWidth / m_worldHeight;
    float imageRatio = static_cast<float>(texWidth) / texHeight;

    float scaleX, scaleY;
    int scaledWidth, scaledHeight;

    if (imageRatio > worldRatio) {
        // 图片比世界更宽，以高度为准
        scaleY = m_worldHeight / texHeight;
        scaleX = scaleY;
        scaledWidth = static_cast<int>(texWidth * scaleX);
        scaledHeight = static_cast<int>(m_worldHeight);
    }
    else {
        // 图片比世界更高或比例相同，以宽度为准
        scaleX = m_worldWidth / texWidth;
        scaleY = scaleX;
        scaledWidth = static_cast<int>(m_worldWidth);
        scaledHeight = static_cast<int>(texHeight * scaleY);
    }

    // 计算背景在world中的居中位置
    float bgWorldX = (m_worldWidth - scaledWidth) / 2.0f;
    float bgWorldY = (m_worldHeight - scaledHeight) / 2.0f;

    // 计算相对于摄像机的位置
    float bgScreenX = bgWorldX - (offset.x * m_parallaxFactor.x);
    float bgScreenY = bgWorldY - (offset.y * m_parallaxFactor.y);

    // 计算在屏幕上的可见区域
    float visibleLeft = (std::max)(bgScreenX, 0.0f);
    float visibleTop = (std::max)(bgScreenY, 0.0f);
    float visibleRight = (std::min)(bgScreenX + scaledWidth, static_cast<float>(screenWidth));
    float visibleBottom = (std::min)(bgScreenY + scaledHeight, static_cast<float>(screenHeight));

    // 如果有可见区域，则渲染
    if (visibleRight > visibleLeft && visibleBottom > visibleTop) {
        // 计算源图像中对应的区域
        float srcLeft = (visibleLeft - bgScreenX) / scaledWidth * texWidth;
        float srcTop = (visibleTop - bgScreenY) / scaledHeight * texHeight;
        float srcRight = (visibleRight - bgScreenX) / scaledWidth * texWidth;
        float srcBottom = (visibleBottom - bgScreenY) / scaledHeight * texHeight;

        int srcX = static_cast<int>(srcLeft);
        int srcY = static_cast<int>(srcTop);
        int srcW = static_cast<int>(srcRight - srcLeft);
        int srcH = static_cast<int>(srcBottom - srcTop);

        int destX = static_cast<int>(visibleLeft);
        int destY = static_cast<int>(visibleTop);
        int destW = static_cast<int>(visibleRight - visibleLeft);
        int destH = static_cast<int>(visibleBottom - visibleTop);
        // 确保参数有效
        if (srcW > 0 && srcH > 0 && destW > 0 && destH > 0 &&
            srcX >= 0 && srcY >= 0 && srcX + srcW <= texWidth && srcY + srcH <= texHeight) {
            // 使用 putimage 的正确重载
            putimage(destX, destY, destW, destH, image, srcX, srcY, SRCCOPY);
        }
    }
}

void BackgroundRenderer::SetAutoFitWorld(bool keepRatio)
{
    if (!HasValidTexture()) {
        std::cout << "[Background] No valid texture loaded, cannot set auto fit mode" << std::endl;
        return;
    }

    int texWidth = GetWidth();
    int texHeight = GetHeight();

    if (texWidth <= 0 || texHeight <= 0) {
        std::cout << "[Background] Invalid texture dimensions" << std::endl;
        return;
    }

    float worldRatio = m_worldWidth / m_worldHeight;
    float imageRatio = static_cast<float>(texWidth) / texHeight;

    if (keepRatio) {
        // 保持比例的模式
        SetRenderMode(RenderMode::FitWorldKeepRatio);
        std::cout << "[Background] Auto-fit mode: FitWorldKeepRatio (World: "
            << m_worldWidth << "x" << m_worldHeight
            << ", Image: " << texWidth << "x" << texHeight
            << ", Ratios: World=" << worldRatio << ", Image=" << imageRatio << ")" << std::endl;
    }
    else {
        // 完全适应世界大小，可能会拉伸
        SetRenderMode(RenderMode::FitWorld);
        std::cout << "[Background] Auto-fit mode: FitWorld (stretch to world size)" << std::endl;
    }
}
